package utl.mofen.script;

import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import utl.mofen.utils.GsonUtil;

public class ScriptObject {
	/**
	 * 源脚本字符串
	 */
	private String dataScript = null;
	
	
	private String key = null;
	
	private String ver = null;
			
	public ScriptObject(String key, String ver)
	{
		this.key = key.toLowerCase();
		this.ver = ver.toLowerCase();
	}
	
	
	/**
	 * 整个数据
	 */
	private JsonObject data = null;	
	
	
	/**
	 * 脚本
	 */
	private JsonObject scrp = null;		
	
	/**
	 * 参数
	 * {"@mm_Key":{"type":"uniqueidentifier","kind":""},}
	 */
	private Hashtable<String, JsonElement> param = new Hashtable<String, JsonElement>();
	
	/**
	 * 替换参数
	 * {"$rep_type":{"oName":"$rep_type"},"$rep_where":{"oName":"$rep_Where"}}
	 */
	private Hashtable<String, JsonElement> repl = new Hashtable<String, JsonElement>();
	
	
	/**
	 * 子脚本 
	 * "subitems": { 
	 *   "list": 
	 *   [
	 *     {"key":11100014,"step":1,"repl":"[#SUBITEM(11100014,1)]"},
	 *     {"key":11100014,"step":1,"repl":"[#SUBITEM(11100014,1)]"}, 
	 *   ], 
	 *   "count":2
	 * },
	 */
	private JsonObject subItems = null;
	
	/**
	 * 解析子脚本
	 * @param soc
	 * @throws Exception 
	 */
	public void parseSubItems(ScriptObjectCenter soc, String strVer) throws Exception
	{
		if ((subItems!=null) && (subItems.getAsJsonObject().get("list")!=null))
		{		
			JsonArray list = subItems.getAsJsonObject().get("list").getAsJsonArray();		
			Iterator<JsonElement> it = list.iterator();
		
			if (list.size() > 0)
			{
				String s = this.getScriptString();
				while (it.hasNext()) {
					JsonObject item = it.next().getAsJsonObject();
					
					String lvKey = item.get("key").getAsString().toLowerCase();
					
					ScriptObject itemObj = null;
					if (lvKey.equals(this.key))
					{
						itemObj = this;
					} else
					{
						itemObj = soc.getScriptObject(lvKey, strVer);
						this.mergeParamAndRepl(itemObj);
					}								
					
					String sec = itemObj.getSectionScript(item.get("step").getAsInt());				
					
					s = s.replace(item.get("repl").getAsString(), sec);				
					
					it.remove();
				}
				
				this.setScriptString(s);			
	    	}
		}
	}

	public String getDataScript() {
		return dataScript;
	}
	
	
	private void innerMerge(Hashtable<String, JsonElement> ht, Iterator<Entry<String, JsonElement>> param_it)
	{
		while(param_it.hasNext())
		{
			Entry<String, JsonElement> e = param_it.next();			
			
			String p_name = e.getKey().toLowerCase();
			
			if (!ht.containsKey(p_name))
			{
				ht.put(p_name, e.getValue());				
			}
		}
	}
	
	/**
	 * 
	 * @param vParam
	 * {"@mm_Key":{"type":"uniqueidentifier","kind":""},}
	 */
	public void mergeParam(JsonObject vParam)
	{
			
		Set<Map.Entry<String, JsonElement>> paramSet = 
				vParam.getAsJsonObject().entrySet();
		Iterator<Entry<String, JsonElement>> param_it = paramSet.iterator();
		this.innerMerge(this.param, param_it);
	}
	

	/**
	 * 
	 * @param vParam
	 * {"$rep_type":{"oName":"$rep_type"},"$rep_where":{"oName":"$rep_Where"}}
	 */
	public void mergeRepl(JsonObject vRepl)
	{
			
		Set<Map.Entry<String, JsonElement>> paramSet = 
				vRepl.getAsJsonObject().entrySet();
		Iterator<Entry<String, JsonElement>> param_it = paramSet.iterator();
		this.innerMerge(this.repl, param_it);		
		
	}

	public void setDataScript(String dataScript) {
		this.dataScript = dataScript;
		data = new JsonParser().parse(dataScript).getAsJsonObject();		
		scrp = data.get("script").getAsJsonObject();		
		subItems = data.get("subitems").getAsJsonObject();
		this.mergeRepl(data.get("repl").getAsJsonObject());
		this.mergeParam(data.get("param").getAsJsonObject());
	}
	
	public String getScriptString()
	{
		return GsonUtil.json2String(scrp);
	}
	
	public void setScriptString(String scriptString)
	{
		scrp = GsonUtil.parse(scriptString).getAsJsonObject();
	}
	
	public void mergeParamAndRepl(ScriptObject obj)
	{
		innerMerge(this.param, obj.param.entrySet().iterator());
		innerMerge(this.repl, obj.repl.entrySet().iterator());
	}
	
	public String getSectionScript(int step)
	{
		JsonElement sec = scrp.get("sec_" + String.valueOf(step));

		if (sec != null) {
			return sec.getAsString();
		}else
		{
			return "";
		}		
	}

	public JsonObject getSubItems() {
		return subItems;
	}

	public Hashtable<String, JsonElement> getParam() {
		return param;
	}

	public Hashtable<String, JsonElement> getRepl() {
		return repl;
	}
}
